package com.qf.blog.controller;

import com.alibaba.druid.util.Utils;
import com.qf.blog.commons.constant.BlogConstants;
import com.qf.blog.commons.utils.CookieUtil;
import com.qf.blog.commons.utils.HttpUtils;
import com.qf.blog.commons.utils.Result;
import com.qf.blog.commons.utils.UserThreadLocal;
import com.qf.blog.dto.IndexDiscussPostDto;
import com.qf.blog.dto.MyPage;
import com.qf.blog.dto.TokenDto;
import com.qf.blog.dto.UserDTO;
import com.qf.blog.entity.User;
import com.qf.blog.handler.BlogException;
import com.qf.blog.service.DiscussPostService;
import com.qf.blog.service.UserService;
import com.qf.blog.vo.RepasswordVo;
import com.qf.blog.vo.UserVo;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * User: key
 * ClassName:UserController
 * Date: 2023/6/2
 * Time: 19:39
 * description:
 */
@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private DiscussPostService postService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @GetMapping("/list")
    @CrossOrigin(value = "http://127.0.0.1:8002/")
    @ResponseBody
    public List<UserDTO> list(){
        List<UserDTO> userDTOList = new ArrayList<>();
        List<User> list = userService.list();
        for (User user : list) {
            UserDTO userDTO = new UserDTO();
            userDTO.setId(user.getId());
            userDTO.setUsername(user.getUsername());
            userDTO.setPassword(user.getPassword());
            userDTO.setHeaderUrl(user.getHeaderUrl());
            userDTO.setCreateTime(user.getCreateTime());
            userDTO.setStatus(user.getStatus());
            userDTO.setEmail(user.getEmail());
            userDTO.setType(user.getType());
            userDTO.setSalt(user.getSalt());
            userDTO.setActivationCode(user.getActivationCode());
            userDTOList.add(userDTO);
        }
        return userDTOList;
    }

    @PostMapping("/add/{dto}")
    public Boolean add(@PathVariable("dto") UserDTO dto){
        User user = new User();
        user.setSalt(dto.getSalt());
        user.setId(dto.getId());
        user.setUsername(dto.getUsername());
        user.setActivationCode(dto.getActivationCode());
        user.setCreateTime(dto.getCreateTime());
        user.setStatus(dto.getStatus());
        user.setHeaderUrl(dto.getHeaderUrl());
        user.setEmail(dto.getEmail());
        user.setType(dto.getType());
        user.setPassword(dto.getPassword());
        return userService.save(user);
    }

    @PutMapping("/update/{dto}")
    public Boolean update(@PathVariable("dto")UserDTO dto){
        Integer id = dto.getId();
        User user = userService.getById(id);
        user.setSalt(dto.getSalt());
        user.setId(dto.getId());
        user.setUsername(dto.getUsername());
        user.setActivationCode(dto.getActivationCode());
        user.setCreateTime(dto.getCreateTime());
        user.setStatus(dto.getStatus());
        user.setHeaderUrl(dto.getHeaderUrl());
        user.setEmail(dto.getEmail());
        user.setType(dto.getType());
        user.setPassword(dto.getPassword());
        return userService.save(user);
    }


    @GetMapping("/select/{id}")
    public UserDTO select(@PathVariable("id") Integer id){
        User user = userService.getById(id);
        UserDTO userDTO = new UserDTO();
        userDTO.setId(user.getId());
        userDTO.setUsername(user.getUsername());
        userDTO.setPassword(user.getPassword());
        userDTO.setHeaderUrl(user.getHeaderUrl());
        userDTO.setCreateTime(user.getCreateTime());
        userDTO.setStatus(user.getStatus());
        userDTO.setEmail(user.getEmail());
        userDTO.setType(user.getType());
        userDTO.setSalt(user.getSalt());
        userDTO.setActivationCode(user.getActivationCode());
        return userDTO;
    }

    @DeleteMapping("/delete/{ids}")
    public Boolean delete(@PathVariable("ids") Integer[] ids){
        boolean empty = ObjectUtils.isEmpty(ids);
        if(!empty){
            List<Integer> list = new ArrayList<>();
            for (Integer id : ids) {
                list.add(id);
            }
            userService.removeBatchByIds(list);
            return true;
        }
        return false;
    }


    @PostMapping("/register")
    @ResponseBody
    @CrossOrigin
    public Result register(@RequestBody UserVo userVo) {
        if (ObjectUtils.isEmpty(userVo.getUsername())) {
            throw new BlogException(1001, "用户名不能为空");
        }
        if (ObjectUtils.isEmpty(userVo.getPwd())) {
            throw new BlogException(1001, "密码不能为空");
        }
        if (ObjectUtils.isEmpty(userVo.getEmail())) {
            throw new BlogException(1001, "邮箱不能为空");
        }
        userService.register(userVo);
        return Result.ok();
    }

    @RequestMapping("/activation")
    @ResponseBody
    public Result activation(String code) {

        // 1.非空校验
        if (ObjectUtils.isEmpty(code)) {
            throw new BlogException(1001, "code不能为空");
        }
        // 2.根据用户的激活码更新状态
        Integer status = userService.updateUserStatus(code);

        if (status <= 0) {
            throw new BlogException(1002, "激活有误或者账号已经激活");
        }
        return Result.ok("恭喜您，激活成功，请返回登陆页面进行登录");
    }

    @PostMapping("/login")
    @ResponseBody
    @CrossOrigin
    public Result login(@RequestBody UserVo userVo, HttpServletResponse resp) {
        //获取前端传回的用户信息
        String username = userVo.getUsername();
        String password = userVo.getPwd();
        //用户信息为空则抛异常
        if (ObjectUtils.isEmpty(username)) {
            throw new BlogException(1001, "用户名不能为空");
        }
        if (ObjectUtils.isEmpty(password)) {
            throw new BlogException(1001, "密码不能为空");
        }
        //根据用户名查找用户
        User user = userService.getUserByUsername(username);
        TokenDto tokenDto = userService.login(username, password);
        //判断用户信息是否正确，不匹配则抛异常
        if (user == null) {
            throw new BlogException(1002, "用户名不存在");
        }
        if (!BCrypt.checkpw(password, user.getPassword())) {
            throw new BlogException(1002, "用户名或密码错误");
        }
        if (user.getStatus() != 1) {
            throw new BlogException(1002, "账户未激活");
        }
        Cookie cookie = new Cookie(BlogConstants.LOGIN_COOKIE_KEY, tokenDto.getUuid());
        cookie.setPath("/");
        cookie.setMaxAge(60 * 30 * 1000);
        resp.addCookie(cookie);
        return Result.ok();
    }

    @GetMapping("/logout")
    public String logout(HttpServletResponse resp) {
        // 注销
        Cookie cookie = CookieUtil.getCookie(BlogConstants.LOGIN_COOKIE_KEY, null, 0);
        redisTemplate.delete(BlogConstants.LOGIN_COOKIE_KEY);
        resp.addCookie(cookie);
        // 重定向到首页
        return "redirect:/";
    }

    @PostMapping("/password")
    public String repass(RepasswordVo repasswordVo, HttpServletResponse resp) {
        //进行密码校验
        dataValidate(repasswordVo);
        TokenDto tokenDto = new TokenDto();
        Integer id = tokenDto.getUserId();
        User user = userService.getById(id);
        if (!BCrypt.checkpw(repasswordVo.getOldPassword(), user.getPassword())) {
            throw new BlogException(1003, "原密码不正确");
        }
        String newPwHash = BCrypt.hashpw(repasswordVo.getNewPassword(), BCrypt.gensalt());
        user.setPassword(newPwHash);
        userService.updateById(user);
//        session.invalidate(); // 注销
        Cookie cookie = CookieUtil.getCookie(BlogConstants.LOGIN_COOKIE_KEY, null, 0);
        redisTemplate.delete(BlogConstants.LOGIN_COOKIE_KEY);
        resp.addCookie(cookie);
        return "redirect:/site/login.html";
    }

    /*
     * 个人主页的我的帖子页面
     * 未合并最新最热，模糊查询也未合并
     * */
    @RequestMapping("/discuss")
    public String discuss(Integer entityId, Model model,
                          MyPage<IndexDiscussPostDto> page,
                          @RequestParam(defaultValue = "0") Integer orderMode) {
        page = postService.indexDiscussPostData(page, orderMode, entityId);
        page.setPath("/discuss?entityId=" + entityId);
        model.addAttribute("page", page);
        return "index";
    }

    private void dataValidate(RepasswordVo repasswordVo) {
        if (ObjectUtils.isEmpty(repasswordVo.getOldPassword())) {
            throw new BlogException(1001, "密码不能为空");
        }
        if (ObjectUtils.isEmpty(repasswordVo.getNewPassword())) {
            throw new BlogException(1001, "新密码不能为空");
        }
        if (ObjectUtils.isEmpty(repasswordVo.getConfirmPassword())) {
            throw new BlogException(1001, "确认密码不能为空");
        }
        if (!repasswordVo.getConfirmPassword().equals(repasswordVo.getNewPassword())) {
            throw new BlogException(1001, "两次密码不一致");
        }
    }
}
